/*
 * mysql_thread.cpp
 *
 *  Created on: 2013-12-19
 *      Author: lixingyi
 */

#include <errno.h>

#include "framework/network_util.h"
#include "framework/time_util.h"
#include "framework/system_util.h"

#include "mysql_thread.h"

#include "proxy_thread.h"
#include "log_thread.h"
#include "proxy_application.h"

#define time_printf(fmt,args...) do{printf("%ld," fmt,time_ms(),##args) ; }while(0)

using namespace kingnet ;

MysqlThread::MysqlThread():m_drizzle(NULL),m_conn(NULL),m_last_time(0),m_reload_flag(false)
{
    // TODO Auto-generated constructor stub

    pthread_mutex_init(&m_mutex,NULL);
    pthread_cond_init(&m_cond,NULL);
}

MysqlThread::~MysqlThread()
{
    // TODO Auto-generated destructor stub

    pthread_cond_destroy(&m_cond); 
    pthread_mutex_destroy(&m_mutex); 
}



int MysqlThread::on_init()
{
    //if(m_request_queue.init(1024)!=0) error_return(-1,"init queue failed");

    
    m_drizzle = drizzle_create() ;
    if(m_drizzle == NULL ) error_return(-1,"init drizzle failed") ;
    
    drizzle_set_context(m_drizzle,this) ;
    drizzle_set_timeout(m_drizzle,5000) ;
    drizzle_set_option(m_drizzle,DRIZZLE_FREE_OBJECTS,true) ;
    //drizzle_set_option(m_drizzle, DRIZZLE_NON_BLOCKING, true);
    
    
    m_conn= drizzle_con_add_tcp(m_drizzle,m_config.host(), m_config.port(), 
        m_config.username(),m_config.password(),m_config.dbname(), DRIZZLE_CON_MYSQL);
    
    if(m_conn == NULL ) error_return(-1,"create conn failed") ;
    
    if( drizzle_query_str(m_conn,&m_result,"set names utf8",NULL) == NULL )
    {
        error_return(-1,"query failed")   ;
    }

    if(drizzle_result_buffer(&m_result)!=DRIZZLE_RETURN_OK)
    {
        drizzle_result_free(&m_result) ;
        error_return(-1,"result failed") ;
    }

    drizzle_result_free(&m_result) ;
    
    set_thread_title("mysql_thread");
    thread_info_log(get_app().log_thread(),"mysql_thread [%d] %s:%d:%s started",
        m_config.id(),m_config.host(),m_config.port(),m_config.dbname() );
    return 0 ;
}

void MysqlThread::on_fini()
{
    run_once() ;

    thread_info_log(get_app().log_thread(),"mysql_thread [%d] stopped",m_config.id() );
    /*
    DrizzleRequest* request = NULL ;
    while(m_request_queue.pop(request) ==true  ) delete request ;
    */

    drizzle_free(m_drizzle);

}



void MysqlThread::run_once()
{
    int now_time = time(0) ;
    if(now_time - m_last_time > 60)
    {
        m_last_time = now_time ;
        on_timer() ;
    }

    if( m_request_queue.empty() )
    {
        struct timespec ts = {0} ;
        ts.tv_sec = time(0) + 2 ;
        //no shared status , so ignore mutex
        //pthread_mutex_lock(&m_mutex);
        pthread_cond_timedwait(&m_cond,&m_mutex,&ts) ;
        //pthread_mutex_unlock(&m_mutex);
    }

    DrizzleRequest* request  = NULL ;
    while( m_request_queue.pop(request) == true )
    {
        if( request->source()->running()  )
        {
            DrizzleResponse* response = new DrizzleResponse ;
            if(response)
            {
                if( on_request(request,response) != 0 || 
                    request->source()->push_response(response)!= true )
                {
                     thread_warn_log(get_app().log_thread(),"mysql_thread [%d] response queue full",m_config.id() );
                     delete response ;
                }
             }
        }
        
        delete request ;

    }

    
}




void MysqlThread::on_timer()
{
    drizzle_return_t ret ;
    drizzle_result_st* result = drizzle_con_ping(m_conn,&m_result,&ret) ;
    if(result) drizzle_result_free(result) ;
    else thread_warn_log(get_app().log_thread(),"ping failed");
}

int MysqlThread::on_request(DrizzleRequest* request,DrizzleResponse* response)
{
    thread_debug_log(get_app().log_thread(),"mysql_thread request [%d] %s\n",m_config.id(),request->sql()) ;
    drizzle_result_st * result = response->result() ;
    if( drizzle_query_str(m_conn,result,request->sql(),NULL) == NULL )
    {
        thread_warn_log(get_app().log_thread(),"mysql_thread [%d] query failed:%s:%s\n",
            m_config.id(),request->sql(),drizzle_error(m_drizzle) ) ;
        drizzle_result_set_error_code(result,1146) ;
    }

    if(drizzle_result_buffer(result)!=DRIZZLE_RETURN_OK)
    {
        drizzle_result_free(result) ;
        thread_warn_log(get_app().log_thread(),"mysql_thread [%d] result error:%s\n",m_config.id(),drizzle_error(m_drizzle) ) ;
    }    

    drizzle_result_detach(result) ;

    return 0 ;
}


